﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Common;
using System.Data;

namespace Brilliant.ORM
{
    /// <summary>
    /// DataProvider基类
    /// </summary>
    public abstract class DataProviderBase
    {
        #region 成员变量
        private DbCommand cmd;
        private DbConnection conn;
        private DbTransaction trans;
        private string connectionString;
        private bool transaction = false; //是否开启事务处理
        private int transLevel = 0; //事务嵌套层次
        #endregion

        #region 属性
        /// <summary>
        /// 是否开始事务处理
        /// </summary>
        public bool Transaction
        {
            get { return this.transaction; }
        }

        /// <summary>
        /// 连接字符串
        /// </summary>
        public string ConnectionString
        {
            get
            {
                return this.connectionString;
            }
        }
        #endregion

        #region 构造器
        /// <summary>
        /// 构造器
        /// </summary>
        /// <param name="connectionString">连接字符串</param>
        public DataProviderBase(string connectionString)
        {
            this.connectionString = connectionString;
        }
        #endregion

        #region 方法
        /// <summary>
        /// 返回Command对象
        /// </summary>
        private DbCommand GetCommand(DbConnection conn, SQL sql)
        {
            if (conn.State != ConnectionState.Open)
            {
                conn.Open();
            }
            DbCommand cmd = GetCommand();
            cmd.Connection = conn;
            cmd.CommandText = sql.CmdText;
            cmd.CommandType = sql.CmdType;
            if (sql.Parameters != null)
            {
                cmd.Parameters.Clear();
                cmd.Parameters.AddRange(sql.Parameters);
            }
            return cmd;
        }

        /// <summary>
        /// 开启事务
        /// </summary>
        public void BeginTransaction()
        {
            //如果未开启事务
            if (this.transaction == false)
            {
                conn = GetConnection();
                conn.Open();
                cmd = GetCommand();
                cmd.Connection = conn;
                trans = conn.BeginTransaction();
                cmd.Transaction = trans;
                this.transaction = true;
            }
            else //如果进行事务嵌套
            {
                transLevel++; //事务层次增加
            }
        }

        /// <summary>
        /// 提交事务
        /// </summary>
        public void Commit()
        {
            //子事务提交时层次递减最后随父事务一起提交
            if (transLevel > 0)
            {
                transLevel--;
                return;
            }
            trans.Commit();
            this.Close();
        }

        /// <summary>
        /// 回滚事务
        /// </summary>
        public void Rollback()
        {
            //任何一个事务异常都立即回滚所有操作
            trans.Rollback();
            this.Close();
        }

        /// <summary>
        /// 关闭事务连接
        /// </summary>
        private void Close()
        {
            if (conn.State != ConnectionState.Closed)
            {
                conn.Close();
                conn.Dispose();
            }
            if (conn != null)
            {
                conn = null;
            }
            trans.Dispose();
            if (trans != null)
            {
                trans = null;
            }
            cmd.Parameters.Clear();
            cmd.Dispose();
            if (cmd != null)
            {
                cmd = null;
            }
            this.transaction = false;
            this.transLevel = 0;
        }

        /// <summary>
        /// 执行查询指令返回DataSet对象
        /// </summary>
        /// <param name="sql">查询指令</param>
        /// <returns>DataSet对象</returns>
        public DataSet ExecDataSet(SQL sql)
        {
            using (DbConnection conn = GetConnection())
            {
                DbCommand cmd = GetCommand(conn, sql);
                DbDataAdapter da = GetDataAdapter();
                da.SelectCommand = cmd;
                DataSet ds = new DataSet();
                da.Fill(ds);
                cmd.Parameters.Clear();
                return ds;
            }
        }

        /// <summary>
        /// 执行查询指令返回DataReader对象
        /// </summary>
        /// <param name="sql">查询指令</param>
        /// <returns>DataReader对象</returns>
        public IDataReader ExecDataReader(SQL sql)
        {
            DbConnection conn = GetConnection();
            DbCommand cmd = GetCommand(conn, sql);
            IDataReader dataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
            cmd.Parameters.Clear();
            return dataReader;
        }

        /// <summary>
        /// 执行查询指令返回第一行第一列的值
        /// </summary>
        /// <param name="sql">查询指令</param>
        /// <returns>第一行第一列的值</returns>
        public object ExecScalar(SQL sql)
        {
            using (DbConnection conn = GetConnection())
            {
                DbCommand cmd = GetCommand(conn, sql);
                object result = cmd.ExecuteScalar();
                cmd.Parameters.Clear();
                return result;
            }
        }

        /// <summary>
        /// 执行查询指令返回受影响行数
        /// </summary>
        /// <param name="sql">查询指令</param>
        /// <returns>受影响行数</returns>
        public int ExecNonQuerry(SQL sql)
        {
            if (this.transaction)
            {
                cmd.CommandText = sql.CmdText;
                cmd.CommandType = sql.CmdType;
                if (sql.Parameters != null)
                {
                    cmd.Parameters.Clear();
                    cmd.Parameters.AddRange(sql.Parameters);
                }
                int result = cmd.ExecuteNonQuery();
                cmd.Parameters.Clear();
                return result;
            }
            else
            {
                using (DbConnection conn = GetConnection())
                {
                    DbCommand cmd = GetCommand(conn, sql);
                    int result = cmd.ExecuteNonQuery();
                    cmd.Parameters.Clear();
                    return result;
                }
            }
        }

        /// <summary>
        /// 批量执行查询指令返回受影响行数(事务)
        /// </summary>
        /// <param name="sqlList">查询指令列表</param>
        /// <returns>受影响行数</returns>
        public int ExecTrans(List<SQL> sqlList)
        {
            int count = 0;
            try
            {
                BeginTransaction();
                foreach (SQL sql in sqlList)
                {
                    count += ExecNonQuerry(sql);
                }
                Commit();
            }
            catch
            {
                Rollback();
                count = 0;
            }
            return count;
        }
        #endregion

        #region 虚方法
        /// <summary>
        /// 返回一个新的Connection实例
        /// </summary>
        /// <returns>Connection实例</returns>
        protected abstract DbConnection GetConnection();

        /// <summary>
        /// 返回一个新的Command实例
        /// </summary>
        /// <returns>Command实例</returns>
        protected abstract DbCommand GetCommand();

        /// <summary>
        /// 返回一个新的DataAdapter实例
        /// </summary>
        /// <returns>DataAdapter实例</returns>
        protected abstract DbDataAdapter GetDataAdapter();
        #endregion
    }
}
